﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Reactive.Linq;
using System.Windows.Media;
using Bull.Core;
using FirstFloor.ModernUI.Presentation;

namespace Bull.UI.ViewModels
{
    public class SettingsAppearanceViewModel : ViewModelBase
    {
        private const string FONT_SMALL = "small";
        private const string FONT_LARGE = "large";

        private const string PALETTE_METRO = "metro";
        private const string PALETTE_WP = "windows phone";

        // 9 accent colors from metro design principles
        private readonly Color[] _metroAccentColors =
        {
            Color.FromRgb(0x33, 0x99, 0xff), // blue
            Color.FromRgb(0x00, 0xab, 0xa9), // teal
            Color.FromRgb(0x33, 0x99, 0x33), // green
            Color.FromRgb(0x8c, 0xbf, 0x26), // lime
            Color.FromRgb(0xf0, 0x96, 0x09), // orange
            Color.FromRgb(0xff, 0x45, 0x00), // orange red
            Color.FromRgb(0xe5, 0x14, 0x00), // red
            Color.FromRgb(0xff, 0x00, 0x97), // magenta
            Color.FromRgb(0xa2, 0x00, 0xff) // purple            
        };

        private readonly LinkCollection _themes = new LinkCollection();

        // 20 accent colors from Windows Phone 8
        private readonly Color[] _wpAccentColors =
        {
            Color.FromRgb(0xa4, 0xc4, 0x00), // lime
            Color.FromRgb(0x60, 0xa9, 0x17), // green
            Color.FromRgb(0x00, 0x8a, 0x00), // emerald
            Color.FromRgb(0x00, 0xab, 0xa9), // teal
            Color.FromRgb(0x1b, 0xa1, 0xe2), // cyan
            Color.FromRgb(0x00, 0x50, 0xef), // cobalt
            Color.FromRgb(0x6a, 0x00, 0xff), // indigo
            Color.FromRgb(0xaa, 0x00, 0xff), // violet
            Color.FromRgb(0xf4, 0x72, 0xd0), // pink
            Color.FromRgb(0xd8, 0x00, 0x73), // magenta
            Color.FromRgb(0xa2, 0x00, 0x25), // crimson
            Color.FromRgb(0xe5, 0x14, 0x00), // red
            Color.FromRgb(0xfa, 0x68, 0x00), // orange
            Color.FromRgb(0xf0, 0xa3, 0x0a), // amber
            Color.FromRgb(0xe3, 0xc8, 0x00), // yellow
            Color.FromRgb(0x82, 0x5a, 0x2c), // brown
            Color.FromRgb(0x6d, 0x87, 0x64), // olive
            Color.FromRgb(0x64, 0x76, 0x87), // steel
            Color.FromRgb(0x76, 0x60, 0x8a), // mauve
            Color.FromRgb(0x87, 0x79, 0x4e) // taupe
        };

        private Color _selectedAccentColor;
        private string _selectedFontSize;
        private string _selectedPalette = PALETTE_METRO;
        private Link _selectedTheme;

        public SettingsAppearanceViewModel()
        {
            // add the default themes
            _themes.Add(new Link {DisplayName = "dark", Source = AppearanceManager.DarkThemeSource});
            _themes.Add(new Link {DisplayName = "light", Source = AppearanceManager.LightThemeSource});

            SelectedFontSize = AppearanceManager.Current.FontSize == FontSize.Large ? FONT_LARGE : FONT_SMALL;
            SelectedTheme = _themes.FirstOrDefault();
            SyncThemeAndColor();

            Observable.FromEventPattern<PropertyChangedEventHandler, PropertyChangedEventArgs>(
                handler => AppearanceManager.Current.PropertyChanged += handler,
                handler => AppearanceManager.Current.PropertyChanged -= handler)
                .Select(result => result.EventArgs.PropertyName == "ThemeSource" || result.EventArgs.PropertyName == "AccentColor")
                .Subscribe(result => SyncThemeAndColor());
        }

        public LinkCollection Themes
        {
            get { return _themes; }
        }

        public string[] FontSizes
        {
            get { return new[] {FONT_SMALL, FONT_LARGE}; }
        }

        public string[] Palettes
        {
            get { return new[] {PALETTE_METRO, PALETTE_WP}; }
        }

        public Color[] AccentColors
        {
            get { return _selectedPalette == PALETTE_METRO ? _metroAccentColors : _wpAccentColors; }
        }

        public string SelectedPalette
        {
            get { return _selectedPalette; }
            set
            {
                if (_selectedPalette != value)
                {
                    _selectedPalette = value;
                    OnPropertyChanged("AccentColors");

                    SelectedAccentColor = AccentColors.FirstOrDefault();
                }
            }
        }

        public Link SelectedTheme
        {
            get { return _selectedTheme; }
            set
            {
                if (_selectedTheme != value)
                {
                    _selectedTheme = value;
                    OnPropertyChanged("SelectedTheme");

                    // and update the actual theme
                    AppearanceManager.Current.ThemeSource = value.Source;
                }
            }
        }

        public string SelectedFontSize
        {
            get { return _selectedFontSize; }
            set
            {
                if (_selectedFontSize != value)
                {
                    _selectedFontSize = value;
                    OnPropertyChanged("SelectedFontSize");

                    AppearanceManager.Current.FontSize = value == FONT_LARGE ? FontSize.Large : FontSize.Small;
                }
            }
        }

        public Color SelectedAccentColor
        {
            get { return _selectedAccentColor; }
            set
            {
                if (_selectedAccentColor != value)
                {
                    _selectedAccentColor = value;
                    OnPropertyChanged("SelectedAccentColor");

                    AppearanceManager.Current.AccentColor = value;
                }
            }
        }

        private void SyncThemeAndColor()
        {
            // synchronizes the selected viewmodel theme with the actual theme used by the appearance manager.
            SelectedTheme = _themes.FirstOrDefault(l => l.Source.Equals(AppearanceManager.Current.ThemeSource));

            // and make sure accent color is up-to-date
            SelectedAccentColor = AppearanceManager.Current.AccentColor;
        }

        
    }
}